using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Threading.Tasks;
using Admin.NET.Application.Entity.Business;
using Admin.NET.Application.Excel;
using Admin.NET.Core;
using Furion;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;

namespace Admin.NET.Application;

/// <summary>
/// 采集器2服务
/// </summary>
[ApiDescriptionSettings(new string[] { "业务应用" }, Order = 100)]
public class ModuleCollectorService : IDynamicApiController, ITransient, IPrivateDependency
{
	private readonly SqlSugarRepository<ModuleCollector> _rep;

	private readonly UserManager _userManager;

	public ModuleCollectorService(SqlSugarRepository<ModuleCollector> rep, UserManager userManager)
	{
		_rep = rep;
		_userManager = userManager;
	}

	/// <summary>
	/// 设备导出
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/moduleCollector/pageexcel")]
	public async Task<IActionResult> ExportDevice([FromQuery] ModuleCollectorInput input)
	{
		ISugarQueryable<ModuleCollector> query = _rep.Context.Queryable<ModuleCollector>().WhereIF(!string.IsNullOrWhiteSpace(input.Name), (ModuleCollector u) => u.Name.Contains(input.Name.Trim())).WhereIF(!string.IsNullOrWhiteSpace(input.Imei), (ModuleCollector u) => u.Imei.Contains(input.Imei.Trim()));
		ISugarQueryable<ModuleCollectorDto> info = query.Select((ModuleCollector u) => new ModuleCollectorDto
		{
			Id = u.Id,
			FirmwareVersion = u.FirmwareVersion,
			Iccid = u.Iccid,
			Imei = u.Imei,
			LastOnlineTime = u.LastOnlineTime,
			Latitude = u.Latitude,
			Longitude = u.Longitude,
			ModuleCollectorGroupId = u.ModuleCollectorGroupId,
			Name = u.Name,
			Version = u.Version,
			ProtocolType = u.ProtocolType,
			ModuleCollectorGroupName = from s4 in SqlFunc.Subqueryable<ModuleCollectorGroup>()
				where (long?)s4.Id == u.ModuleCollectorGroupId
				select s4.Name
		}).OrderBuilder(input);
		string str = "模组设备-" + DateTime.Now.ToString("yyyy-MM-dd");
		List<string> column = new List<string>();
		List<string> title = new List<string>();
		column.AddRange(new string[4] { "Imei", "Name", "ModuleCollectorGroupName", "Iccid" });
		title.AddRange(new string[4] { "序列号", "设备名称", "分组名称", "sim卡号" });
		MemoryStream memery = ExportToExcel.ExportToList(info.ToArray(), str, str, column.ToArray(), title.ToArray());
		App.HttpContext.Response.ContentType = "application/vnd.ms-excel";
		byte[] aa = memery.ToArray();
		return new FileStreamResult(new MemoryStream(aa), "application/octet-stream")
		{
			FileDownloadName = str + ".xlsx"
		};
	}

	/// <summary>
	/// 上传文件 导入设备
	/// </summary>
	/// <param name="file"></param>
	/// <param name="path"></param>
	/// <returns></returns>
	[HttpPost("/moduleCollector/uploadpdf")]
	public async Task UploadFile([Required] IFormFile file, string path = "")
	{
		try
		{
			ExcelUtil excelUtil = new ExcelUtil();
			List<ModuleCollectorDto> list = excelUtil.ExcelToList<ModuleCollectorDto>(file, new Dictionary<string, string>
			{
				{ "序列号", "Imei" },
				{ "名称", "Name" },
				{ "分组", "ModuleCollectorGroupName" }
			});
			if (list.Where((ModuleCollectorDto u) => string.IsNullOrWhiteSpace(u.Imei) || string.IsNullOrWhiteSpace(u.Name)).Any())
			{
				throw Oops.Oh("当前存在空值");
			}
			List<string> imeilist = list.Select((ModuleCollectorDto i) => i.Imei).ToList();
			ModuleCollector eleModel = await (from u in _rep.Context.Queryable<ModuleCollector>().ClearFilter()
				where imeilist.Contains(u.Imei)
				select u).FirstAsync();
			if (eleModel != null)
			{
				throw Oops.Oh("当前表序列号已存在" + eleModel.Imei);
			}
			string disImei = (from u in imeilist
				group u by u into u
				select new
				{
					count = u.Count(),
					sn = u.Key
				} into u
				where u.count > 1
				select u).FirstOrDefault()?.sn;
			if (!string.IsNullOrEmpty(disImei))
			{
				throw Oops.Oh("当前表序列号存在重复" + disImei);
			}
			list.ForEach(delegate(ModuleCollectorDto u)
			{
				u.ModuleCollectorGroupId = Convert.ToInt64(u.ModuleCollectorGroupName.Split('-')[1]);
			});
			List<long?> modelCollectIds = list.Select((ModuleCollectorDto u) => u.ModuleCollectorGroupId).Distinct().ToList();
			int modelCollectInfoCount = await (from u in _rep.Context.Queryable<ModuleCollectorGroup>()
				where u.IsDelete == false && modelCollectIds.Contains(u.Id)
				select u).CountAsync();
			if (modelCollectIds.Count != modelCollectInfoCount)
			{
				throw Oops.Oh("当前数据模板分组已更新，请下载最新模板导入");
			}
			List<DeviceManufacturer> collector = await (from u in _rep.Context.Queryable<DeviceManufacturer>()
				where imeilist.Contains(u.Sn) && u.IsUse == 0
				select u).ToListAsync();
			if (collector.Count != imeilist.Count)
			{
				throw Oops.Oh("当前设备编号有误，不在系统记录，或已被使用，请联系管理员");
			}
			await _rep.Context.Ado.BeginTranAsync();
			string realName = App.User?.FindFirst("RealName")?.Value;
			long userId = Convert.ToInt64(App.User?.FindFirst("UserId")?.Value);
			DateTime now = DateTime.Now;
			List<AddModuleCollectorInput> addInfo = list.Adapt<List<AddModuleCollectorInput>>();
			List<ModuleCollector> entity = addInfo.Adapt<List<ModuleCollector>>();
			collector.ForEach(delegate(DeviceManufacturer u)
			{
				u.IsUse = 1;
				u.UseName = realName;
				u.UseUser = userId;
				u.UseTime = now;
			});
			entity.ForEach(delegate(ModuleCollector u)
			{
				DeviceManufacturer deviceManufacturer = collector.Where((DeviceManufacturer s) => s.Sn == u.Imei).FirstOrDefault();
				u.ProtocolType = deviceManufacturer.ProtocolType;
				u.Version = -1;
			});
			await _rep.Context.Updateable(collector).UpdateColumns((DeviceManufacturer u) => new { u.UseTime, u.UseName, u.UseUser, u.IsUse }).ExecuteCommandAsync();
			_rep.InsertRange(entity.ToArray());
			await _rep.Context.Ado.CommitTranAsync();
		}
		catch (Exception)
		{
			await _rep.Context.Ado.RollbackTranAsync();
			throw;
		}
	}

	/// <summary>
	/// 导出列表excel
	/// </summary>
	/// <returns></returns>
	[HttpPost("/moduleCollector/templeteexcel")]
	public async Task<IActionResult> Templeteexcel()
	{
		string str = "设备模组-" + DateTime.Now.ToString("yyyy-MM-dd");
		List<string> list = new List<string> { "序列号", "名称", "分组" };
		Dictionary<string, List<string>> dic = new Dictionary<string, List<string>> { 
		{
			"分组",
			(await (from u in _rep.Context.Queryable<ModuleCollectorGroup>()
				where u.IsDelete == false
				select new
				{
					value = u.Id,
					label = u.Name
				}).ToListAsync()).Select(u => u.label + "-" + u.value).ToList()
		} };
		ExcelUtil excelUtil = new ExcelUtil();
		MemoryStream stream = excelUtil.GetTemplate(list, dic, str);
		return new FileStreamResult(new MemoryStream(stream.ToArray()), "application/octet-stream")
		{
			FileDownloadName = str + ".xlsx"
		};
	}

	/// <summary>
	/// 获取数据字典
	/// </summary>
	/// <returns></returns>
	[HttpGet("/moduleCollector/getGroup")]
	public async Task<dynamic> Page()
	{
		return await (from u in _rep.Context.Queryable<ModuleCollectorGroup>()
			where u.IsDelete == false
			select new
			{
				value = u.Id,
				label = u.Name
			}).ToListAsync();
	}

	/// <summary>
	/// 分页查询模组分组2
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpGet("/moduleCollector/page")]
	public async Task<dynamic> Page([FromQuery] ModuleCollectorInput input)
	{
		ISugarQueryable<ModuleCollector> query = _rep.Context.Queryable<ModuleCollector>().WhereIF(!string.IsNullOrWhiteSpace(input.Name), (ModuleCollector u) => u.Name.Contains(input.Name.Trim())).WhereIF(!string.IsNullOrWhiteSpace(input.Imei), (ModuleCollector u) => u.Imei.Contains(input.Imei.Trim()))
			.WhereIF(input.Type.HasValue, (ModuleCollector u) => (int?)u.ProtocolType == input.Type)
			.WhereIF(input.ModuleCollectorGroupId > 0, (ModuleCollector u) => u.ModuleCollectorGroupId == input.ModuleCollectorGroupId)
			.WhereIF(input.ModuleCollectorGroupId == 0, (ModuleCollector u) => u.ModuleCollectorGroupId == null);
		ISugarQueryable<ModuleCollectorDto> info = query.Select((ModuleCollector u) => new ModuleCollectorDto
		{
			Id = u.Id,
			FirmwareVersion = u.FirmwareVersion,
			Iccid = u.Iccid,
			Imei = u.Imei,
			LastOnlineTime = u.LastOnlineTime,
			Latitude = u.Latitude,
			Longitude = u.Longitude,
			ModuleCollectorGroupId = u.ModuleCollectorGroupId,
			Name = u.Name,
			Version = u.Version,
			ProtocolType = u.ProtocolType,
			CreateTime = u.CreateTime,
			ModuleCollectorGroupName = from s4 in SqlFunc.Subqueryable<ModuleCollectorGroup>()
				where (long?)s4.Id == u.ModuleCollectorGroupId
				select s4.Name
		}).OrderBuilder(input);
		return await info.ToPagedListAsync(input.Page, input.PageSize);
	}

	/// <summary>
	/// 增加模组分组2
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/moduleCollector/add")]
	public async Task Add(AddModuleCollectorInput input)
	{
		try
		{
			ModuleCollector entity = input.Adapt<ModuleCollector>();
			if (await _rep.Context.Queryable<ModuleCollector>().ClearFilter().AnyAsync((ModuleCollector u) => u.Imei == entity.Imei))
			{
				throw Oops.Oh(ErrorCodeEnum.R2002);
			}
			DeviceManufacturer collector = await (from u in _rep.Context.Queryable<DeviceManufacturer>()
				where u.Sn == input.Imei
				select u).FirstAsync();
			if (collector == null)
			{
				throw Oops.Oh("当前设备编号有误，不在系统记录，请重新输入");
			}
			if (collector.IsUse == 1)
			{
				throw Oops.Oh("当前设备编号已使用，请检查后重新输入");
			}
			await _rep.Context.Ado.BeginTranAsync();
			collector.IsUse = 1;
			string realName = App.User?.FindFirst("RealName")?.Value;
			long userId = Convert.ToInt64(App.User?.FindFirst("UserId")?.Value);
			collector.UseName = realName;
			collector.UseUser = userId;
			collector.UseTime = DateTime.Now;
			entity.ProtocolType = collector.ProtocolType;
			entity.Version = -1;
			await _rep.Context.Updateable(collector).UpdateColumns((DeviceManufacturer u) => new { u.UseTime, u.UseName, u.UseUser, u.IsUse }).ExecuteCommandAsync();
			await _rep.InsertAsync(entity);
			await _rep.Context.Ado.CommitTranAsync();
		}
		catch (Exception ex)
		{
			await _rep.Context.Ado.RollbackTranAsync();
			if (!(ex is Exception source))
			{
				throw ex;
			}
			ExceptionDispatchInfo.Capture(source).Throw();
		}
	}

	/// <summary>
	/// 删除模组分组2
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/moduleCollector/delete")]
	public async Task Delete(DeleteModuleCollectorInput input)
	{
		try
		{
			ModuleCollector entity = await _rep.GetFirstAsync((ModuleCollector u) => u.Id == input.Id);
			DeviceManufacturer collector = await (from u in _rep.Context.Queryable<DeviceManufacturer>()
				where u.Sn == entity.Imei
				select u).FirstAsync();
			if (collector == null)
			{
				throw Oops.Oh("当前设备编号有误，不在系统记录，请重新输入");
			}
			await _rep.Context.Ado.BeginTranAsync();
			collector.IsUse = 0;
			_ = App.User?.FindFirst("RealName")?.Value;
			Convert.ToInt64(App.User?.FindFirst("UserId")?.Value);
			collector.UseName = null;
			collector.UseUser = null;
			collector.UseTime = null;
			await _rep.Context.Updateable(collector).UpdateColumns((DeviceManufacturer u) => new { u.UseTime, u.UseName, u.UseUser, u.IsUse }).ExecuteCommandAsync();
			await _rep.DeleteAsync(entity);
			await _rep.Context.Ado.CommitTranAsync();
		}
		catch (Exception ex)
		{
			await _rep.Context.Ado.RollbackTranAsync();
			if (!(ex is Exception source))
			{
				throw ex;
			}
			ExceptionDispatchInfo.Capture(source).Throw();
		}
	}

	/// <summary>
	/// 更新模组分组2
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/moduleCollector/edit")]
	public async Task Update(UpdateModuleCollectorInput input)
	{
		DeviceManufacturer collector = await (from u in _rep.Context.Queryable<DeviceManufacturer>()
			where u.Sn == input.Imei
			select u).FirstAsync();
		if (collector == null)
		{
			throw Oops.Oh("当前设备编号有误，不在系统记录，请重新输入");
		}
		ModuleCollector entity = input.Adapt<ModuleCollector>();
		entity.ProtocolType = collector.ProtocolType;
		if (await _rep.IsAnyAsync((ModuleCollector u) => u.Imei == entity.Imei && u.Id != entity.Id))
		{
			throw Oops.Oh(ErrorCodeEnum.R2002);
		}
		if ((await _rep.GetFirstAsync((ModuleCollector u) => u.Id == entity.Id)).ModuleCollectorGroupId != entity.ModuleCollectorGroupId)
		{
			entity.Version = -1;
			await _rep.Context.Updateable(entity).UpdateColumns((ModuleCollector u) => new { u.Name, u.ModuleCollectorGroupId, u.ProtocolType, u.Version }).ExecuteCommandAsync();
		}
		else
		{
			await _rep.Context.Updateable(entity).UpdateColumns((ModuleCollector u) => new { u.Name, u.ProtocolType, u.ModuleCollectorGroupId }).ExecuteCommandAsync();
		}
	}

	/// <summary>
	/// 获取模组分组信息
	/// </summary>
	/// <returns></returns>
	[HttpGet("/moduleCollector/allgroups")]
	public async Task<dynamic> GetModuleGroupCollectors()
	{
		return await (from u in _rep.Context.Queryable<ModuleCollectorGroup>()
			select new { u.Id, u.Name }).ToListAsync();
	}

	/// <summary>
	/// 批量修改分组
	/// </summary>
	/// <param name="groupId"></param>
	/// <param name="moduleIds"></param>
	/// <returns></returns>
	[HttpPost("/moduleCollector/changegroup")]
	public async Task ChangeGroup([FromQuery] long? groupId, [FromBody] List<long> moduleIds)
	{
		if (moduleIds.Count == 0)
		{
			throw Oops.Bah("请至少选择一个模组");
		}
		if (groupId > 0 && !(await (from u in _rep.Context.Queryable<ModuleCollectorGroup>()
			where (long?)u.Id == groupId
			select u).AnyAsync()))
		{
			throw Oops.Bah("当前选择的分组不存在或已被删除，请刷新后重试");
		}
		if (groupId == 0)
		{
			groupId = null;
		}
		await (from u in _rep.Context.Updateable<ModuleCollector>().SetColumns((ModuleCollector u) => u.ModuleCollectorGroupId == groupId).SetColumns((ModuleCollector u) => u.Version == (int?)(-1))
			where moduleIds.Contains(u.Id)
			select u).ExecuteCommandAsync();
	}

	/// <summary>
	/// 转移模组到指定用户账户
	/// </summary>
	/// <param name="groupId"></param>
	/// <param name="moduleIds"></param>
	/// <returns></returns>
	[HttpPost("/moduleCollector/changeuser")]
	public async Task ChangeUser([FromQuery] string account, [FromBody] List<long> moduleIds)
	{
		if (moduleIds.Count == 0)
		{
			throw Oops.Bah("请至少选择一个模组");
		}
		if (!_userManager.SuperAdmin && account == _userManager.Account)
		{
			throw Oops.Bah("请转移给其他账户");
		}
		SysUser user = await (from u in _rep.Context.Queryable<SysUser>().ClearFilter()
			where u.Account == account
			select u).FirstAsync();
		if (user == null)
		{
			throw Oops.Bah("指定账户不存在");
		}
		DateTime now = DateTime.Now;
		await (from u in _rep.Context.Updateable<ModuleCollector>().SetColumns((ModuleCollector u) => new ModuleCollector
			{
				CreateTime = now,
				CreateUserId = user.Id,
				CreateUserName = user.RealName,
				TenantId = user.TenantId,
				Version = -1,
				ModuleCollectorGroupId = null
			})
			where moduleIds.Contains(u.Id)
			select u).ExecuteCommandAsync();
	}
}
